package com.siao.display
{
	import com.siao.utils.display.measure;
	
	import flash.display.DisplayObject;
	import flash.display.Stage;
	import flash.events.Event;
	
	/**
	 * 布局显示元素
	 * @author SiaoLeon
	 */
	public class LayoutElement extends DisplayElement
	{
		// -------------------------------------------------------------------------------------------------------- 静态常量
		
		// -------------------------------------------------------------------------------------------------------- 静态变量
		
		// -------------------------------------------------------------------------------------------------------- 静态方法
		
		// -------------------------------------------------------------------------------------------------------- 静态函数
		
		// -------------------------------------------------------------------------------------------------------- 属性
		
		private var _x:Number;
		
		override public function get x():Number
		{
			return (isNaN(this._x)) ? 0 : this._x;
		}
		
		override public function set x(value:Number):void
		{
			this._x = value;
			
			this.resize();
		}
		
		private var _y:Number;
		
		override public function get y():Number
		{
			return (isNaN(this._y)) ? 0 : this._y;
		}
		
		override public function set y(value:Number):void
		{
			this._y = value;
			
			this.resize();
		}
		
		private var _width:Number;
		
		override public function get width():Number
		{
			return Math.max(0, this.range.width);
		}
		
		override public function set width(value:Number):void
		{
			this._width = this.range.width = value;
			
			this.layout();
		}
		
		private var _height:Number;
		
		override public function get height():Number
		{
			return Math.max(0, this.range.height);
		}
		
		override public function set height(value:Number):void
		{
			this._height = this.range.height = value;
			
			this.layout();
		}
		
		override public function set visible(value:Boolean):void
		{
			if (super.visible == value)
			{
				return;
			}
			
			super.visible = value;
			
			if (value)
			{
				this.init();
			}
			else
			{
				this.exit();
			}
		}
		
		private var _maxWidth:Number;
		
		/**
		 * 最大宽度
		 * @return
		 */
		public function get maxWidth():Number
		{
			return this._maxWidth;
		}
		
		public function set maxWidth(value:Number):void
		{
			this._maxWidth = value;
			
			this.resize();
		}
		
		private var _maxHeight:Number;
		
		/**
		 * 最大高度
		 * @return
		 */
		public function get maxHeight():Number
		{
			return this._maxHeight;
		}
		
		public function set maxHeight(value:Number):void
		{
			this._maxHeight = value;
			
			this.resize();
		}
		
		private var _backgroundColor:uint;
		
		/**
		 * 背景颜色
		 * @return
		 */
		public function get backgroundColor():uint
		{
			return this._backgroundColor;
		}
		
		private var _backgroundAlpha:Number;
		
		/**
		 * 背景透明度
		 * @return
		 */
		public function get backgroundAlpha():Number
		{
			return this._backgroundAlpha;
		}
		
		private var _alignH:uint = Align.NONE;
		
		/**
		 * 横向对齐方式
		 * @return
		 */
		public function get alignH():uint
		{
			return this._alignH;
		}
		
		public function set alignH(value:uint):void
		{
			this._alignH = value;
			
			this.position();
		}
		
		private var _alignV:uint = Align.NONE;
		
		/**
		 * 纵向对齐方式
		 * @return
		 */
		public function get alignV():uint
		{
			return this._alignV;
		}
		
		public function set alignV(value:uint):void
		{
			this._alignV = value;
			
			this.position();
		}
		
		private var _offsetX:Number = 0;
		
		/**
		 * X轴偏移量
		 * @return
		 */
		public function get offsetX():Number
		{
			return this._offsetX;
		}
		
		public function set offsetX(value:Number):void
		{
			this._offsetX = value;
			
			this.position();
		}
		
		private var _offsetY:Number = 0;
		
		/**
		 * Y轴偏移量
		 * @return
		 */
		public function get offsetY():Number
		{
			return this._offsetY;
		}
		
		public function set offsetY(value:Number):void
		{
			this._offsetY = value;
			
			this.position();
		}
		
		/**
		 * 内边距
		 * @return
		 */
		public function set padding(value:Number):void
		{
			this.range.left = this.range.top = this.range.right = this.range.bottom = value;
			
			this.layout();
		}
		
		/**
		 * 左侧内边距
		 * @return
		 */
		public function get paddingLeft():Number
		{
			return this.range.left;
		}
		
		public function set paddingLeft(value:Number):void
		{
			this.range.left = value;
			
			this.layout();
		}
		
		/**
		 * 右侧内边距
		 * @return
		 */
		public function get paddingRight():Number
		{
			return this.range.right;
		}
		
		public function set paddingRight(value:Number):void
		{
			this.range.right = value;
			
			this.layout();
		}
		
		/**
		 * 顶部内边距
		 * @return
		 */
		public function get paddingTop():Number
		{
			return this.range.top;
		}
		
		public function set paddingTop(value:Number):void
		{
			this.range.top = value;
			
			this.layout();
		}
		
		/**
		 * 底部内边距
		 * @return
		 */
		public function get paddingBottom():Number
		{
			return this.range.bottom;
		}
		
		public function set paddingBottom(value:Number):void
		{
			this.range.bottom = value;
			
			this.layout();
		}
		
		private var _margin:Margin = new Margin();
		
		/**
		 * 外边距
		 * @param value
		 */
		public function set margin(value:Number):void
		{
			this._margin.left = this._margin.top = this._margin.right = this._margin.bottom = value;
			
			this.layout();
		}
		
		/**
		 * 左侧外边距
		 * @return
		 */
		public function get marginLeft():Number
		{
			return this._margin.left;
		}
		
		public function set marginLeft(value:Number):void
		{
			this._margin.left = value;
			
			this.layout();
		}
		
		/**
		 * 右侧外边距
		 * @return
		 */
		public function get marginRight():Number
		{
			return this._margin.right;
		}
		
		public function set marginRight(value:Number):void
		{
			this._margin.right = value;
			
			this.layout();
		}
		
		/**
		 * 顶部外边距
		 * @return
		 */
		public function get marginTop():Number
		{
			return this._margin.top;
		}
		
		public function set marginTop(value:Number):void
		{
			this._margin.top = value;
			
			this.layout();
		}
		
		/**
		 * 底部外边距
		 * @return
		 */
		public function get marginBottom():Number
		{
			return this._margin.bottom;
		}
		
		public function set marginBottom(value:Number):void
		{
			this._margin.bottom = value;
			
			this.layout();
		}
		
		private var _range:Range = new Range();
		
		/**
		 * 实际内容显示范围
		 * @return
		 */
		public function get range():Range
		{
			return this._range;
		}
		
		/**
		 * 实际内容显示范围
		 * @return
		 */
		public function set range(value:Range):void
		{
			this._range = value;
			
			this.layout();
		}
		
		// -------------------------------------------------------------------------------------------------------- 变量
		
		// -------------------------------------------------------------------------------------------------------- 构造
		
		/**
		 * 构造函数
		 */
		public function LayoutElement()
		{
			super();
		}
		
		// -------------------------------------------------------------------------------------------------------- 方法
		
		override public function clear():void
		{
			super.clear();
			
			this.graphics.clear();
		}
		
		/**
		 * 获取外边距
		 * @return
		 */
		public function getMargin():Margin
		{
			return this._margin;
		}
		
		/**
		 * 绘制背景
		 */
		public function draw(backgroundColor:uint=0X000000, backgroundAlpha:Number=1.0):void
		{
			this._backgroundColor = backgroundColor;
			this._backgroundAlpha = backgroundAlpha;
			
			this.graphics.clear();
			
			if (!isNaN(this.backgroundAlpha) && !isNaN(this.backgroundColor))
			{
				this.graphics.beginFill(this.backgroundColor, this.backgroundAlpha);
				this.graphics.drawRect(0, 0, this.width, this.height);
				this.graphics.endFill();
			}
		}
		
		/**
		 * 布局子级
		 */
		public function layout():void
		{
			if (this.stage == null || !this.visible)
			{
				return;
			}
			
			this.resize();
			
			for (var i:int = 0; i < this.numChildren; i++)
			{
				if (this.getChildAt(i) is LayoutElement)
				{
					(this.getChildAt(i) as LayoutElement).layout();
				}
			}
		}
		
		/**
		 * 调整尺寸
		 */
		public function resize():void
		{
			if (this.stage == null || !this.visible)
			{
				return;
			}
			
			var rect:Range = this.getAvailableRange();
			var thumbX:Number = (this.alignH == Align.NONE && !isNaN(this._x)) ? this._x : this.marginLeft + this.marginRight;
			var thumbY:Number = (this.alignV == Align.NONE && !isNaN(this._y)) ? this._y : this.marginTop + this.marginBottom;
			
			this.range.width = (isNaN(this._width)) ? (this.parent is Stage) ? this.stage.stageWidth : rect.width - rect.left - rect.right - thumbX : this._width;
			this.range.height = (isNaN(this._height)) ? (this.parent is Stage) ? this.stage.stageHeight : rect.height - rect.top - rect.bottom - thumbY : this._height;
			
			this.range.width = (isNaN(this.maxWidth)) ? this.range.width : Math.max(0, Math.min(this.maxWidth, this.range.width));
			this.range.height = (isNaN(this.maxHeight)) ? this.range.height : Math.max(0, Math.min(this.maxHeight, this.range.height));
			
			this.position(rect);
			
			this.draw(this.backgroundColor, this.backgroundAlpha);
		}
		
		/**
		 * 根据指定范围定位，如不指定范围则在父级中定位
		 */
		public function position(rect:Range=null):void
		{
			if (this.stage == null || !this.visible)
			{
				return;
			}
			
			if (rect == null)
			{
				rect = this.getAvailableRange();
			}
			
			switch (this.alignH)
			{
				case Align.NONE:
					var x:Number = (isNaN(this._x)) ? this.marginLeft : this._x;
					super.x = (this.parent is LayoutElement) ? rect.left + x + this.offsetX : x + this.offsetX;
					break;
				
				case Align.CENTER:
					this._x = (rect.width - this.width) / 2;
					super.x = this._x + this.offsetX;
					break;
				
				case Align.LEFT:
					this._x = rect.left + this.marginLeft;
					super.x = this._x + this.offsetX;
					break;
				
				case Align.RIGHT:
					this._x = rect.width - rect.right - this.marginRight - this.width;
					super.x = this._x + this.offsetX;
					break;
			}
			
			switch (this.alignV)
			{
				case Align.NONE:
					var y:Number = (isNaN(this._y)) ? this.marginTop : this._y;
					super.y = (this.parent is LayoutElement) ? rect.top + y + this.offsetY : y + this.offsetY;
					break;
				
				case Align.CENTER:
					this._y = (rect.height - this.height) / 2;
					super.y = this._y + this.offsetY;
					break;
				
				case Align.TOP:
					this._y = rect.top + this.marginTop;
					super.y = this._y + this.offsetY;
					break;
				
				case Align.BOTTOM:
					this._y = rect.height - rect.bottom - this.marginBottom - this.height;
					super.y = this._y + this.offsetY;
					break;
			}
		}
		
		/**
		 * 重置
		 */
		public function reset():void
		{
			this._x = this._y = Number.NaN;
			this._width = this._height = Number.NaN;
			this._maxWidth = this._maxHeight = Number.NaN;
			this._alignH = this._alignV = 0;
			this._offsetX = this._offsetY = 0;
			this._range.left = this._range.right = this._range.top = this._range.bottom = this._range.width = this._range.height = 0;
			this._margin.left = this._margin.right = this._margin.top = this._margin.bottom = 0;
			
			this.resize();
		}
		
		// -------------------------------------------------------------------------------------------------------- 函数
		
		override internal final function addedToStageHandler(event:Event):void
		{
			this.init();
			
			super.addedToStageHandler(event);
		}
		
		override internal final function removedFromStageHandler(event:Event):void
		{
			this.exit();
			
			super.removedFromStageHandler(event);
		}
		
		/**
		 * 初始化
		 */
		protected function init():void
		{
			this.resize();
		}
		
		/**
		 * 退出
		 */
		protected function exit():void
		{
		}
		
		/**
		 * 获取容器的实际可用范围
		 * @return
		 */
		protected function getAvailableRange():Range
		{
			if (this.parent == null)
			{
				return new Range();
			}
			
			//如果父级是Stage则直接返回Stage显示范围
			if (this.parent is Stage)
			{
				return new Range(this.stage.stageWidth, this.stage.stageHeight);
			}
			
			//如果父级是LayoutElement则直接返回实际显示范围
			if (this.parent is LayoutElement)
			{
				return (this.parent as LayoutElement).range;
			}
			
			var ignoreH:Array = new Array();
			var ignoreV:Array = new Array();
			
			for (var i:int = 0; i < this.parent.numChildren; i++)
			{
				var child:DisplayObject = this.parent.getChildAt(i);
				
				if (child == this)
				{
					ignoreH.push(child);
					ignoreV.push(child);
					continue;
				}
				
				if (child is LayoutElement && (child as LayoutElement).alignH != Align.NONE)
				{
					ignoreH.push(child);
				}
				
				if (child is LayoutElement && (child as LayoutElement).alignV != Align.NONE)
				{
					ignoreV.push(child);
				}
			}
			
			return measure(this.parent, ignoreH, ignoreV);
		}
	
	}
}
